package com.qing.demo.netty.codec;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.nio.charset.Charset;
import java.util.List;

/**
 * @author caozhipeng
 * @date 2025/7/25
 * 解码器
 */
public class MyDecoder extends ByteToMessageDecoder {

    // 定义协议的长度
    private  final int HEADER_LENGTH = 4;
    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
//       基础长度不足，协议长度4
        if(byteBuf.readableBytes() < HEADER_LENGTH){
            return;
        }
//        记录包头位置
        int beginIdx;
        while (true){
//            获取包头开始的index
            beginIdx=byteBuf.readerIndex();
//            标记包头开始的index位置
            byteBuf.markReaderIndex();
//            读到协议开始的标志02，结束循环
            if(byteBuf.readByte()== 0x02){
                break;
            }
//            未读到包头，略过一个字节，再次读取
//            每次略过，一个字节，去读取，包头信息的开始标记
            byteBuf.resetReaderIndex();
            byteBuf.readByte();
//            当略过，一个字节之后，未到包头，且已读到的数据，小于包头长度，则，结束循环，等待后续数据到达
            if(byteBuf.readableBytes()<HEADER_LENGTH){
                return;
            }
        }
//        剩余长度不足可以读数量，【没有内容长度位】
        int readableCount=byteBuf.readableBytes();
        if(readableCount<=1){
            byteBuf.readerIndex(beginIdx);
            return;
        }
//        长度域占4字节，读取int
        ByteBuf buf=byteBuf.readBytes(1);
        String msgLengthStr=buf.toString(Charset.forName("utf-8"));
        int msgLength=Integer.parseInt(msgLengthStr);

//        剩余长度不足可以读取数量【没有结尾标识】
        readableCount=byteBuf.readableBytes();
        if(readableCount<msgLength+1){
            byteBuf.readerIndex(beginIdx);
            return;
        }

        ByteBuf msgContent=byteBuf.readBytes(msgLength);
//        如果没有结尾标识，还原指针位置【其它结尾标识】
        byte end=byteBuf.readByte();
        if(end!=0x03){
            byteBuf.readerIndex(beginIdx);
            return;
        }
//        读取消息 内容
        list.add(msgContent.toString(Charset.forName("utf-8")));
    }
}
